package com.zpb.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zpb.admin.domain.entity.AdminUserInfoVo;
import com.zpb.framework.domain.ApiResult;
import com.zpb.framework.domain.entity.Menu;
import com.zpb.framework.domain.entity.User;
import com.zpb.framework.domain.entity.UserInfo;
import com.zpb.framework.domain.enums.ResultCodeEnum;
import com.zpb.framework.domain.vo.LoginVo;
import com.zpb.admin.domain.vo.MenuTreeVo;
import com.zpb.framework.domain.vo.UserVo;
import com.zpb.framework.mapper.MenuMapper;
import com.zpb.framework.mapper.RoleMapper;
import com.zpb.framework.mapper.UserMapper;
import com.zpb.framework.utils.*;
import com.zpb.admin.service.AdminLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: zhaopengbo
 * @Date: 2025/9/11
 */
@Service
public class AdminLoginServiceImpl implements AdminLoginService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    public ApiResult<Map<String, Object>> login(LoginVo user) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (authenticate == null) {
            throw new RuntimeException("用户名或密码错误");
        }
        // 如果认证通过，使用userId生成一个jwt返回
        UserInfo userInfo = (UserInfo) authenticate.getPrincipal();
        Long userId = userInfo.getUser().getId();
        String jwt = JwtUtil.createJWT(userId.toString());
        Map<String, Object> map = new HashMap<>();
        map.put("token", jwt);
        // 把完整的用户信息存入Redis userId作为key
        redisCache.setCacheObject("adminLogin:" + userId, userInfo);
        return ApiResult.success(map, "登录成功");
    }

    @Override
    public ApiResult logout() {
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        UserInfo userInfo = (UserInfo) authentication.getPrincipal();
        Long userId = userInfo.getUser().getId();
        redisCache.deleteObject("adminLogin:" + userId);
        return ApiResult.success();
    }

    @Override
    public ApiResult<AdminUserInfoVo> getInfo() {
        Long currentId = SecurityUtils.getCurrentId();
        User user = userMapper.selectById(currentId);
        if (user == null) {
            return ApiResult.failure(ResultCodeEnum.NO_USER);
        }
        UserVo userVo = BeanCopyUtil.copyBean(user, UserVo.class);
        List<String> permissions = null;
        List<String> roleKeys = null;

        if (SecurityUtils.isAdmin()) {
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Menu::getStatus, DictCodeUtil.NORMAL_STATUS);
            List<Menu> menus = menuMapper.selectList(queryWrapper);
            if (menus == null || menus.size() == 0) {
                return ApiResult.error(ResultCodeEnum.UNKNOWN_ERROR.getMsg());
            }
            permissions = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            roleKeys = new ArrayList<>();
            roleKeys.add("admin");


        }else{
            permissions = menuMapper.selectMenuPermsByUserId(currentId);
            roleKeys = roleMapper.getRoleKeysByUserId(currentId);
        }

        AdminUserInfoVo adminUserInfoVo = new AdminUserInfoVo(permissions, roleKeys, userVo);
        return ApiResult.success(adminUserInfoVo);
    }

    @Override
    public ApiResult<Map<String, Object>> getRouters() {
        Map<String, Object> map = new HashMap<>();
        List<Menu> menus =null;
        if(SecurityUtils.isAdmin()){
            menus = menuMapper.selectAllMenu();
        }else{
            menus = menuMapper.selectMenuByUserId(SecurityUtils.getCurrentId());
        }

        List<MenuTreeVo> menuTreeVos = BeanCopyUtil.copyBeanList(menus, MenuTreeVo.class);
        List<MenuTreeVo> parentMenuTreeVo = menuTreeVos.stream()
                .filter(m -> m.getParentId().equals(0L))
                .collect(Collectors.toList());
        parentMenuTreeVo.forEach(m -> {
            m.setChildren(buildMenuTree(m.getId(), menuTreeVos));
        });

        map.put("menus", parentMenuTreeVo);

        return ApiResult.success(map);
    }

    public List<MenuTreeVo> buildMenuTree(Long parentId, List<MenuTreeVo> menuTreeVos) {

        List<MenuTreeVo> children = menuTreeVos.stream()
                .filter(m -> m.getParentId().equals(parentId))
                .collect(Collectors.toList());
        children.stream()
                .forEach(m -> {
                    m.setChildren(buildMenuTree(m.getId(), menuTreeVos));
                });
        return children;
    }
}
